package socket;

import jdk.internal.util.xml.impl.Input;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/*
 * 聊天室客户端
 * */
public class Client {
    /*
     * java.net.Socket 套接字
     * Socket封装了TCP协议的通讯细节，
     * 是我们使用它就可以与远程计算机建立链接
     * 并基于两条流(输入流/输出流)的读写完成与远端计算机的数据交互
     *
     * 客户端的输出流和服务端的输入流链接
     * 服务端的输入流和客户端的输出流链接
     * */
    private Socket socket;

    /*
     * 构造方法用来初始化客户端，主要工作是与服务端建立TCP建立
     * */
    public Client() {
        /*
         * Socket常用的构造器
         * Scoket(String host,int port)
         * 参数1:要连接的服务
         * 参数2:服务器上服务端所使用的端口号
         * */
        try {
            /*
             * 实例化Socket对象时就是开始连接服务器的一个过程
             * */
            System.out.println("开始链接服务器！");
            /*
             * Socket实例中的host参数为服务器IP
             * socket实例中的port参数为服务器上服务端在服务端上所使用的端口号
             *
             * 客户端不用主动向服务端发送自己的ip和端口
             * 服务器会根据客户端的传输信息来获取
             * */
            socket = new Socket("111.197.58.1", 8088);
            System.out.println("连接成功！");
        } catch (IOException e) {
            /*
             * 因为当前电脑上8088端口没有在使用 所以链接事变
             * */
            System.out.println("链接失败！");
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            //启动用多线程循环读取服务端广发的信息的线程
            Runnable r = new ServerHandler();
            Thread t = new Thread(r);
            //将此线程设置为守护线程，当进程中的所有其他线程都执行结束后，此线程直接就被杀死
            t.setDaemon(true);
            t.start();

            //Soket.getOutputStream获取一个字节输出流，同样是一个低级流，从这个流写出的字节将会发送给对象
            OutputStream outputStream = socket.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            PrintWriter printWriter = new PrintWriter(bufferedWriter, true); //打开自动行刷新

            //利用循环实现重复向服务端发送信息
            Scanner scanner = new Scanner(System.in);
            while (true) {
                System.out.print("消息: ");
                String line = scanner.nextLine();
                //如果用户输入exit循环结束
                if ("exit".equals(line)) {
                    break;
                }
                //printlin()是PrintWriter类提供的方法 它可以实现按行输出字符串和实现自动行刷新功能
                printWriter.println("向服务端发送:" + line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                /*
                 * socket中的close方法提供的功能
                 * 1.调用时会自动关闭通过socket获取的输入流和输出流
                 * 2.与对方进行四次挥手断开操作
                 * */
                socket.close();
            } catch (IOException e) {
                System.out.println("您的网络断开链接");
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    /*
     * 此线程用来读取来自服务端发送过来的消息
     * */
    private class ServerHandler implements Runnable {
        @Override
        public void run() {
            try {
                //通过socket获取输入流
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println("来自???的:" + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
